/*
 * Copyright (c) 2010-present www.walkerljl.org All Rights Reserved.
 * The software source code all copyright belongs to the author, 
 * without permission shall not be any reproduction and transmission.
 */
package org.walkerljl.commons.mail;

import org.walkerljl.commons.util.ArraysUtils;

import java.util.*;

/**
 * CommonEmail
 *
 * @author lijunlin
 */
public abstract class CommonEmail {

    public static final String X_PRIORITY = "X-Priority";

    public static final int PRIORITY_HIGHEST = 1;
    public static final int PRIORITY_HIGH = 2;
    public static final int PRIORITY_NORMAL = 3;
    public static final int PRIORITY_LOW = 4;
    public static final int PRIORITY_LOWEST = 5;

    // ---------------------------------------------------------------- from

    protected MailAddress from;
    protected MailAddress[] to = MailAddress.EMPTY_ARRAY;
    protected MailAddress[] replyTo = MailAddress.EMPTY_ARRAY;

    // ---------------------------------------------------------------- to
    protected MailAddress[] cc = MailAddress.EMPTY_ARRAY;
    protected MailAddress[] bcc = MailAddress.EMPTY_ARRAY;
    protected String subject;
    protected String subjectEncoding;

    // ---------------------------------------------------------------- reply-to
    protected List<EmailMessage> messages = new ArrayList<EmailMessage>();
    protected Map<String, String> headers;
    protected Date sentDate;

    /**
     * Returns FROM {@link MailAddress address}.
     */
    public MailAddress getFrom() {
        return from;
    }

    // ---------------------------------------------------------------- cc

    /**
     * Sets the FROM address.
     */
    public void setFrom(MailAddress from) {
        this.from = from;
    }

    /**
     * Appends TO address.
     */
    public void addTo(MailAddress to) {
        this.to = ArraysUtils.append(this.to, to);
    }

    /**
     * Returns TO addresses.
     */
    public MailAddress[] getTo() {
        return to;
    }

    /**
     * Sets TO addresses.
     */
    public void setTo(MailAddress... tos) {
        if (tos == null) {
            tos = MailAddress.EMPTY_ARRAY;
        }
        to = tos;
    }

    // ---------------------------------------------------------------- bcc

    /**
     * Appends REPLY-TO address.
     */
    public void addReplyTo(MailAddress to) {
        this.replyTo =ArraysUtils.append(this.replyTo, to);
    }

    /**
     * Returns REPLY-TO addresses.
     */
    public MailAddress[] getReplyTo() {
        return replyTo;
    }

    /**
     * Sets REPLY-TO addresses.
     */
    public void setReplyTo(MailAddress... replyTo) {
        if (replyTo == null) {
            replyTo = MailAddress.EMPTY_ARRAY;
        }
        this.replyTo = replyTo;
    }

    /**
     * Appends CC address.
     */
    public void addCc(MailAddress to) {
        this.cc = ArraysUtils.append(this.cc, to);
    }

    // ---------------------------------------------------------------- subject

    /**
     * Returns CC addresses.
     */
    public MailAddress[] getCc() {
        return cc;
    }

    /**
     * Sets CC addresses.
     */
    public void setCc(MailAddress... ccs) {
        if (ccs == null) {
            ccs = MailAddress.EMPTY_ARRAY;
        }
        cc = ccs;
    }

    /**
     * Appends BCC address.
     */
    public void addBcc(MailAddress to) {
        this.bcc = ArraysUtils.append(this.bcc, to);
    }

    /**
     * Returns BCC addresses.
     */
    public MailAddress[] getBcc() {
        return bcc;
    }

    /**
     * Sets BCC addresses.
     */
    public void setBcc(MailAddress... bccs) {
        if (bccs == null) {
            bccs = MailAddress.EMPTY_ARRAY;
        }
        bcc = bccs;
    }

    /**
     * Sets message subject with specified encoding to override default platform encoding.
     * If the subject contains non US-ASCII characters, it will be encoded using the specified charset.
     * If the subject contains only US-ASCII characters, no encoding is done and it is used as-is.
     * The application must ensure that the subject does not contain any line breaks.
     * See {@link javax.mail.internet.MimeMessage#setSubject(String, String)}.
     */
    public void setSubject(String subject, String encoding) {
        this.subject = subject;
        this.subjectEncoding = encoding;
    }

    // ---------------------------------------------------------------- message

    /**
     * Returns message subject.
     */
    public String getSubject() {
        return this.subject;
    }

    /**
     * Sets message subject.
     */
    public void setSubject(String subject) {
        this.subject = subject;
    }

    /**
     * Returns the message subject encoding.
     */
    public String getSubjectEncoding() {
        return this.subjectEncoding;
    }

    /**
     * Returns all messages.
     */
    public List<EmailMessage> getAllMessages() {
        return messages;
    }

    public void addMessage(EmailMessage emailMessage) {
        messages.add(emailMessage);
    }

    // ---------------------------------------------------------------- headers

    public void addMessage(String text, String mimeType, String encoding) {
        messages.add(new EmailMessage(text, mimeType, encoding));
    }

    public void addMessage(String text, String mimeType) {
        messages.add(new EmailMessage(text, mimeType));
    }

    /**
     * Returns all headers as a <code>HashMap</code>.
     */
    protected Map<String, String> getAllHeaders() {
        return headers;
    }

    /**
     * Sets a new header value.
     */
    public void setHeader(String name, String value) {
        if (headers == null) {
            headers = new HashMap<String, String>();
        }
        headers.put(name, value);
    }

    public String getHeader(String name) {
        if (headers == null) {
            return null;
        }
        return headers.get(name);
    }

    /**
     * Returns emails priority (1 - 5) or <code>-1</code> if priority not available.
     *
     * @see #setPriority(int)
     */
    public int getPriority() {
        if (headers == null) {
            return -1;
        }
        try {
            return Integer.parseInt(headers.get(X_PRIORITY));
        } catch (NumberFormatException ignore) {
            return -1;
        }
    }


    // ---------------------------------------------------------------- date

    /**
     * Sets email priority.
     * Values of 1 through 5 are acceptable, with 1 being the highest priority, 3 = normal
     * and 5 = lowest priority.
     */
    public void setPriority(int priority) {
        setHeader(X_PRIORITY, String.valueOf(priority));
    }

    /**
     * Returns e-mails sent date. If return value is <code>null</code> then date
     * will be set during the process of sending.
     *
     * @return email's sent date or null if it will be set later.
     */
    public Date getSentDate() {
        return sentDate;
    }

    /**
     * Sets e-mails sent date. If input parameter is <code>null</code> then date
     * will be when email is physically sent.
     */
    public void setSentDate(Date date) {
        sentDate = date;
    }
}
